package com.afeng.web.framework.filter;


import com.afeng.web.common.util.SignUtil;
import com.afeng.web.framework.annotation.ApiAuth;
import com.afeng.web.framework.exception.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * API权限验证
 */
@Slf4j
@Component
public class ApiInterceptor extends HandlerInterceptorAdapter {

    public static final String API_PATH = "api";//API路径名
    private static final String signSecret = "simpleFree2021";//签名盐值
    public static final String signKey = "sign";//签名请求头或URL请求参数key
    public static final String tokenKey = "token";//给客户端响应头或URL请求参数存入token的键


    /**
     * 权限验证，默认需要验证简单签名sign与简单登录token
     * 简单检验登录
     *
     * @author AFeng
     * @date 2020/11/26 14:55
     * @see com.afeng.web.module.app.controller.ApiTestController#authSimpleLogin(String)
     * @see com.afeng.web.framework.filter.AuthHandlerMethodArgumentResolver#resolveArgument
     **/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod;
        if (handler instanceof HandlerMethod) {
            handlerMethod = (HandlerMethod) handler;
        } else {
            return true;
        }
        // 获取方法上的注解
        ApiAuth apiAuth = handlerMethod.getMethodAnnotation(ApiAuth.class);
        if (apiAuth == null) {
            // 如果方法上的注解为空 则获取类的注解
            apiAuth = handlerMethod.getMethod().getDeclaringClass().getAnnotation(ApiAuth.class);
        }
        if (apiAuth != null) {
            //验证签名
            if (apiAuth.isAuthSign()) {
                verifySimpleSign(apiAuth, request, response);
            }
        }

        return true;
    }


    /**
     * 简单检验签名，需要业务自行处理防重放，签名算法 = MD5( data(请求参数) + signSecret )
     *
     * @author AFeng
     * @date 2020/11/19 17:30
     **/
    private void verifySimpleSign(ApiAuth apiAuth, HttpServletRequest request, HttpServletResponse response) throws Exception {

        //获取sign
        String sign = request.getParameter(signKey);
        if (StringUtils.isEmpty(sign)) {
            throw ApiException.toAccessDenied("sign不能为空");
        }

        //签名
        String signAuth = SignUtil.createSimpleSign(request, signSecret);
        log.debug("signAuth = " + signAuth);
        if (!StringUtils.equals(signAuth, sign)) {
            throw ApiException.toAccessDenied("签名验证失败");
        }

    }


}
